/*
 * Copyright:  2018 smarabbit studio.
 *
 *  Licensed under the Confluent Community License; you may not use this file
 *  except in compliance with the License.  You may obtain a copy of the License at
 *
 *  http://www.confluent.io/confluent-community-license
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 *  WARRANTIES OF ANY KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations under the License.
 *
 *  @作   者： 黄开晖 (117227773@qq.com)
 *  @日   期:  2021年5月29日
 */
package com.massyframework.beanskin.runtime.modular.assembly;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;

import com.massyframework.beanskin.ModuleIdentifier;
import com.massyframework.beanskin.ModuleRepository;
import com.massyframework.beanskin.RequireLibraryDescriptor;
import com.massyframework.beanskin.assembly.AssemblyBuilder;
import com.massyframework.beanskin.assembly.ServletModel;
import com.massyframework.beanskin.assembly.beans.BeanContextHandlerFactory;
import com.massyframework.beanskin.runtime.modular.InitParamsBuilder;
import com.massyframework.beanskin.service.DependencyServiceDescriptor;
import com.massyframework.beanskin.service.DependencyServiceDescriptorBuilder;
import com.massyframework.beanskin.service.ExportServiceDescriptor;
import com.massyframework.beanskin.service.ExportServiceDescriptorBuilder;
import com.massyframework.beanskin.service.ServiceRepositoryFactory;
import com.massyframework.beanskin.util.BeanSkinServiceLoaderUtils;
import com.massyframework.beanskin.util.classloading.ModuleClassLoader;
import com.massyframework.beanskin.util.version.VersionRange;

/**
 * 装配件配置构建器
 * @author huangkh
 *
 */
public final class DefaultAssemblyBuilder  extends InitParamsBuilder
	implements AssemblyBuilder{
	
	protected List<String> configLocations;
	protected List<Class<?>> configTypes;
	protected List<DependencyServiceDescriptor<?>> dependencies;
	protected List<ExportServiceDescriptor> exports;
	
	protected ServletModel servletModel = ServletModel.NONE;
	
	protected Map<String, Object> beanMap;
	protected String beanContextName;
	protected VersionRange versionRange;
	protected BeanContextHandlerFactory beanContextHandlerFactory;
	

	@Override
	public AssemblyBuilder addBean(String beanName, Object bean) {
		if (beanName != null && bean != null) {
			if (this.beanMap == null) {
				this.beanMap = new HashMap<>();
			}
			this.beanMap.put(beanName, bean);
		}
		return this;
	}

	@Override
	public DefaultAssemblyBuilder addConfigLocation(String configLocation) {
		if (configLocation != null) {
			if (this.configLocations == null) {
				this.configLocations = new ArrayList<>();
			}
			this.configLocations.add(configLocation);
		}
		return this;
	}

	@Override
	public DefaultAssemblyBuilder addConfigType(Class<?> value) {
		if (value != null) {
			if (this.configTypes == null) {
				this.configTypes = new ArrayList<>();
			}
			this.configTypes.add(value);
		}
		return this;
	}

	@Override
	public DefaultAssemblyBuilder addDependencyService(Consumer<DependencyServiceDescriptorBuilder> action) {
		if (action != null) {
			DependencyServiceDescriptorBuilder builder =
					BeanSkinServiceLoaderUtils.loadService(DependencyServiceDescriptorBuilder.class, this.getClass().getClassLoader());
			action.accept(builder);
			
			if (this.dependencies == null) {
				this.dependencies = new ArrayList<>();
			}
			this.dependencies.add(builder.build());
		}
		return this;
	}
	
	
	@Override
	public AssemblyBuilder addDependencyService(DependencyServiceDescriptor<?> value) {
		if (value != null) {			
			if (this.dependencies == null) {
				this.dependencies = new ArrayList<>();
			}
			this.dependencies.add(value);
		}
		return this;
	}

	@Override
	public AssemblyBuilder addExportService(ExportServiceDescriptor value) {
		if (value != null) {			
			if (this.exports == null) {
				this.exports = new ArrayList<>();
			}
			this.exports.add(value);
		}
		return this;
	}

	@Override
	public DefaultAssemblyBuilder addExportService(Consumer<ExportServiceDescriptorBuilder> action) {
		if (action != null) {
			ExportServiceDescriptorBuilder builder =
					BeanSkinServiceLoaderUtils.loadService(ExportServiceDescriptorBuilder.class, this.getClass().getClassLoader());
			action.accept(builder);
			
			if (this.exports == null) {
				this.exports = new ArrayList<>();
			}
			this.exports.add(builder.build());
		}
		return this;
	}

	@Override
	public DefaultAssemblyBuilder addTags(Set<String> value) {
		super.addTags(value);
		return this;
	}


	@Override
	public DefaultAssemblyBuilder beanContext(String beanContextName, VersionRange versionRange,
			BeanContextHandlerFactory factory) {
		this.beanContextName = beanContextName;
		this.versionRange = versionRange;
		this.beanContextHandlerFactory = factory;
		return this;
	}
	
	@Override
	public DefaultAssemblyBuilder decryption(String publicKey, String x509Name, String x509Encrypted,
			List<String> classNames, List<String> scriptFileNames) {
		super.decryption(publicKey, x509Name, x509Encrypted, classNames, scriptFileNames);
		return this;
	}

	@Override
	public DefaultAssemblyBuilder setServletModel(ServletModel value) {
		this.servletModel = value;
		return this;
	}

	@Override
	public DefaultAssemblyBuilder setParameter(String name, String value) {
		super.setParameter(name, value);
		return this;
	}

	@Override
	public DefaultAssemblyBuilder setParameter(String name, String value, Consumer<Boolean> action) {
		super.setParameter(name, value, action);
		return this;
	}

	@Override
	public DefaultAssemblyBuilder identifier(ModuleIdentifier value) {
		super.identifier(value);
		return this;
	}

	@Override
	public DefaultAssemblyBuilder name(String value) {
		super.name(value);
		return this;
	}

	@Override
	public DefaultAssemblyBuilder description(String value) {
		super.description(value);
		return this;
	}
	
	@Override
	public DefaultAssemblyBuilder developer(String shortName, String name, String homePage) {
		super.developer(shortName, name, homePage);
		return this;
	}

	@Override
	public DefaultAssemblyBuilder addRequireLibrary(RequireLibraryDescriptor value) {
		super.addRequireLibrary(value);
		return this;
	}
	

	@Override
	public DefaultAssemblyBuilder moduleRepository(ModuleRepository value) {
		super.moduleRepository(value);
		return this;
	}
	
	
	@Override
	public DefaultAssemblyBuilder classLoader(ModuleClassLoader value) {
		super.classLoader(value);
		return this;
	}

	@Override
	public DefaultAssemblyBuilder serviceRepositoryFactory(ServiceRepositoryFactory value) {
		super.serviceRepositoryFactory(value);
		return this;
	}

	public DefaultAssembly build() {
		DefaultAssembly result = new DefaultAssembly(this);
		result.init();
		return result;
	}
}
